/**
  * @brief project RealServer, 实现了RealServer类的方法
  * @file RealServer.cpp
  * @author Liu Shuo
  * @date 2011.5.16
  */

#include "RealServer.h"

/**
  * @brief 用于创建线程
  * @param [in] arg: struct request Args *
  * @return NULL
  */
void *thread_handleRequest(void *arg)
{
    Pthread_detach(pthread_self());
    struct requestArgs *ptr = (struct requestArgs *)arg;
    //ptr->topNode->addThreadNum();
    ptr->realServer->handleRequest(ptr->connfd);
    //TopNode *topnode = ptr->topNode;
    //free(ptr->request);
    free(ptr);
    return NULL;
}

/**
  * @brief 用于创建线程
  * @param [in] arg: struct request Args *
  * @return NULL
  */
void *thread_serve(void *arg)
{
    return ((RealServer *)arg)->serve(NULL);
}

/**
  * @brief constructor
  */
RealServer::RealServer()
{
    bzero(&m_LBMesgAddr, sizeof(m_LBMesgAddr));
    m_LBMesgAddr.sin_family = AF_INET;
    Inet_pton(AF_INET, m_LBIP.c_str(), &m_LBMesgAddr.sin_addr);
    m_LBMesgAddr.sin_port = htons(m_LBMesgPort);
}

/**
  * @brief destructor
  */
RealServer::~RealServer()
{
}

/**
  * @brief 向负载均衡器发送心跳
  * @class RealServer
  * @param arg: NULL
  * @return NULL
  */
void *RealServer::heartbeat(void *arg)
{
    int sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in serverAddr;
    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    Inet_pton(AF_INET, m_LBIP.c_str(), &serverAddr.sin_addr);
    serverAddr.sin_port = htons(m_LBHbPort);

    //定时发送心跳
    string heartBeatMessage = "H,";
    heartBeatMessage += m_ID;
    while(1) {
        //cout << "send heartbeat " << heartBeatMessage << endl;
        //printf("处理请求%d\n", m_connNum);
        Sendto(sockfd, heartBeatMessage.c_str(), heartBeatMessage.length(), 0,
            (struct sockaddr *) &serverAddr, sizeof(serverAddr));
        sleep(1);
    }
    return NULL;
}

/**
  * @brief 向LB注册
  * @class RealServer
  * @return 0 表示注册成功
  */
int RealServer::registerToLB()
{
    int sockfd = Socket(AF_INET, SOCK_STREAM, 0);
    char message[MAXLINE] = {0};
    //sprintf(message, "%s,%s,%d,%d\n", "R", m_ID.c_str(), m_servicePort, m_property);
    sprintf(message, "%s,%s,%d\n", "R", m_ID.c_str(), m_servicePort);
    Connect(sockfd, (struct sockaddr *)&m_LBMesgAddr, sizeof(m_LBMesgAddr));
    Writen(sockfd, message, strlen(message));
    Close(sockfd);
    return 0;
}

/**
  * @brief 运行服务器
  * @class RealServer
  */
void RealServer::run()
{
    registerToLB();
    Pthread_create(&m_servicePthread, NULL, thread_serve, (void *)this);
    heartbeat(NULL);
}

void *RealServer::serve(void *arg)
{
    int sockfd = Socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serveraddr, cliaddr;
    int connfd;
    socklen_t clilen = sizeof(cliaddr);
    struct requestArgs* args;
    pthread_t tid;

    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(m_servicePort);
    cout << m_servicePort << endl;

    Bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    Listen(sockfd, 10);

    while (1) {
        args = (struct requestArgs *)Malloc(sizeof(struct requestArgs));
        connfd = Accept(sockfd, (struct sockaddr *)&cliaddr, &clilen);
        args->realServer = this;
        args->connfd = connfd;
        Pthread_create(&tid, NULL, thread_handleRequest, args);
    }
    return NULL;
}

/**
  * @class RealServer
  * @brief 读取配置文件
  * @param [in] filename: 配置文件地址
  */
void RealServer::readConf(char *filename)
{
    FILE *fp = Fopen(filename, "r");
    int num = 0;
    char buf[MAXLINE];

    while (Fgets(buf, MAXLINE, fp) != NULL) {
#ifdef DEBUG
        //cout << buf;
#endif
        if (buf[0] != '#') {
            buf[strlen(buf) - 1] = 0;
            switch (num) {
            case 0:
                m_LBIP.assign(buf);
                break;
            case 1:
                m_LBHbPort = atoi(buf);
                break;
            case 2:
                m_LBMesgPort = atoi(buf);
                break;
            case 3:
                m_ID.assign(buf);
                break;
            case 4:
                m_servicePort = atoi(buf);
                break;
            default:
                break;
            }
            num++;
        }
    }
#ifdef DEBUG
    cout << "the load balancer IP: " << m_lbIP << endl;
    cout << "the load balancer heartbeat port: " << m_lbHbPort << endl;
    cout << "the load balancer message port: " << m_lbMessagePort << endl;
    cout << "node ID: " << m_ID << endl;
    cout << "the service port: " << m_servicePort << endl;
#endif
}

/**
  * @class LoadBanlancer
  * @brief handle the request from client
  * @param [in] connfd: the socket ID of client
  */
void *RealServer::handleRequest(int connfd)
{
    char buf[MAXLINE];
    ssize_t n;
    while((n = read(connfd, buf, MAXLINE)) > 0) {
        buf[n] = 0;
        cout << buf << endl;
        //***********************************
        //*
        //*在这里添加处理请求的代码
        //*
        //**************************************
        Writen(connfd, buf, n);
    }
    Close(connfd);
    return NULL;
}
